package cool.tenyears.util;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;

import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * @Author tenyears
 * @Description 基于Hutool的TreeUtil封装树结构工具, 详情请参考Hutool文档
 * @Date 2021/6/18 23:18
 * @link https://hutool.cn/docs/#/core/%E8%AF%AD%E8%A8%80%E7%89%B9%E6%80%A7/%E6%A0%91%E7%BB%93%E6%9E%84/%E6%A0%91%E7%BB%93%E6%9E%84%E5%B7%A5%E5%85%B7-TreeUtil
 */
public class TreeBuild {
    private static final String COL_ORDER = "orderNum";
    private static final String TOP_ID = "0";

    /**
     * 默认创建树结构方法
     *
     * @param list 业务集合
     * @return 树
     */
    public static List<Tree<String>> build(List<?> list) {
        return build(list, defaultConfig(), TOP_ID, null);
    }

    /**
     * 扩展属性树 --(主要在获取菜单时使用)
     * @param list   业务集合
     * @param fields  扩展属性
     * @return 树
     */
    public static List<Tree<String>> build(List<?> list, String[] fields) {
        return build(list, defaultConfig(), TOP_ID, fields);
    }

    /**
     * 默认配置
     * @return TreeNodeConfig
     */
    private static TreeNodeConfig defaultConfig() {
        TreeNodeConfig config = new TreeNodeConfig();
        config.setWeightKey(COL_ORDER);

        return config;
    }

    /**
     * 完整的树结构构造
     *
     * @param list   业务集合
     * @param config 配置
     * @param topId  最顶级id
     * @param fields  扩展属性
     * @return 树
     */
    public static List<Tree<String>> build(List<?> list, TreeNodeConfig config, String topId, String[] fields) {
        // 传入集合为空时, 直接返回emptyList，但是这个集合是不能修改的, 请注意！
        if (CollUtil.isEmpty(list)) {
            return Collections.emptyList();
        }
        // 将普通集合转为TreeNode
        List<TreeNode<String>> nodeList = CollUtil.newArrayList();
        for (Object o : list) {
            String idValue = Convert.toStr(BeanUtil.getFieldValue(o, config.getIdKey()));
            String parentIdValue = Convert.toStr(BeanUtil.getFieldValue(o, config.getParentIdKey()));
            String nameValue = Convert.toStr(BeanUtil.getFieldValue(o, config.getNameKey()));
            String weightValue = Convert.toStr(BeanUtil.getFieldValue(o, config.getWeightKey()));
            TreeNode<String> node = new TreeNode<>(idValue, parentIdValue, nameValue, weightValue);
            // 获取扩展属性的值
            if (ArrayUtil.isNotEmpty(fields)) {
                Map<String, Object> extra = MapUtil.newHashMap(16);
                for (String field : fields) {
                    extra.put(field, Convert.toStr(BeanUtil.getFieldValue(o, field)));
                }
                node.setExtra(extra);
            }
            nodeList.add(node);
        }
        // 转换器, 转为树结构
        return TreeUtil.build(nodeList, topId, config,
                (treeNode, tree) -> {
                    tree.setId(treeNode.getId());
                    tree.setParentId(treeNode.getParentId());
                    tree.setWeight(treeNode.getWeight());
                    tree.setName(treeNode.getName());
                    // 添加扩展属性
                    if (MapUtil.isNotEmpty(treeNode.getExtra())) {
                        for (Map.Entry<String, Object> entry : treeNode.getExtra().entrySet()) {
                            tree.putExtra(entry.getKey(), entry.getValue());
                        }
                    }
                });
    }

    private TreeBuild() {
    }
}
